//------------------------------------------------------------------------------
// The confidential and proprietary information contained in this file may
// only be used by a person authorised under and to the extent permitted
// by a subsisting licensing agreement from ARM Limited.
//
//            (C) COPYRIGHT 2008-2012 ARM Limited.
//                ALL RIGHTS RESERVED
//
// This entire notice must be reproduced on all copies of this file
// and copies of this file may only be made by a person if such person is
// permitted to do so under the terms of a subsisting license agreement
// from ARM Limited.
//------------------------------------------------------------------------------
// Version and Release Control Information:
//
// File Revision       : 130657
// File Date           :  2012-05-28 17:35:55 +0100 (Mon, 28 May 2012)
// Release Information : PL401-r0p1-00eac0
//------------------------------------------------------------------------------
// Purpose             : This module is responsible for muxing the upsizer R 
//                       data channel, mapping larger RData beats onto the 
//                       smaller upstream data bus.
//                       This module lives in the IB Slave Domain.
//                       This module will also mask the larger rlast to the 
//                       final, narrower rdata beat.
//                       It contains a single register for storing the data this 
//                       is so it can be used without an attached fifo. 
//                       (the V/R will attach directly to the AXI R channel)
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
//
//  Config :
//           o  Outstanding Reads  = 1
//
//------------------------------------------------------------------------------

module nic400_ib_psram_slv_axi4_ib_upsize_rd_chan_ysyx_rv32
  (
  //rchannel Outputs
  rvalid_s,
  rdata_s,
  rlast_s,
  rid_s,
  rresp_s,

  //rchannel Inputs
  rready_s,

  //rchannel Inputs
  rvalid_m,
  rdata_m,
  rlast_m,
  rid_m,
  rresp_m,

  //rchannel Outputs
  rready_m,

  //From the Archannel forward block
  archannel_data,
  archannel_valid,
  archannel_ready,

  aclk,
  aresetn
  );

`include "nic400_ib_psram_slv_axi4_ib_defs_ysyx_rv32.v"

  //System
  input                     aclk;
  input                     aresetn;

  // To/From the Archannel forward block
  input                     archannel_valid;
  output                    archannel_ready;
  input [18:0]              archannel_data;

  // To/From the RFIFO
  input                     rvalid_m;
  output                    rready_m;

  input [63:0]              rdata_m;
  input [3:0]               rid_m;
  input [1:0]               rresp_m;
  input                     rlast_m;

  //Slave Bus rchannel signals
  input                     rready_s;

  output                    rvalid_s;
  output [31:0]             rdata_s;
  output [3:0]              rid_s;
  output [1:0]              rresp_s;
  output                    rlast_s;

   //------------------------------------------------------------------------
   // Wires
   //------------------------------------------------------------------------

   wire                                                archannel_ready_i;
   wire                     match_bus;
   wire                     hazard_bus;
   wire                     valid_bus;
   wire                     last_addr_match_bus;
   wire                     beat_complete_slice_bus;

   wire                     hazard;           //Hazard detected
   wire                     last_addr_match;  //Signal to move to next beat
   wire                     beat_complete_slice;

   wire                     archannel_hndshk;
   wire                     rchannel_hndshk;

   wire                     push_slice;
   wire                     pop_slice;          //push and pop_slice signals for the CAM Slices
   wire                     update;

   wire                     beat_complete;

   wire                     data_select;

   wire                     addr;
   
   wire [3:0]               rid_m;

   //These are signals muxed between data from the rchannel or it's register version
   wire [63:0]              rdata;
   wire                     rlast_in;
   wire                     rlast_s_i;
   wire [1:0]               rresp_s;
   wire                     addr_out0;


   //------------------------------------------------------------------------
   // Regs
   //------------------------------------------------------------------------

   reg [31:0]               rdata_s;

   reg                      hazard_pointer;
   reg                      match_pointer;

   reg                      store;

   //------------------------------------------------------------------------
   // Decode RFIFO data
   //------------------------------------------------------------------------

   assign rid_s = rid_m;
   assign rlast_in = rlast_m;
   assign rresp_s = rresp_m;
   assign rdata = rdata_m;


   //------------------------------------------------------------------------
   // Combine Signals from Cam Slices
   //------------------------------------------------------------------------

   //Hazard
   assign hazard = hazard_bus;

   //Last
   assign last_addr_match = (last_addr_match_bus & match_bus);

   //Bypass
   assign beat_complete_slice = (beat_complete_slice_bus & match_bus);

   //Select addr values;
   assign addr = addr_out0;

   //------------------------------------------------------------------------
   // Calculate address increment
   //------------------------------------------------------------------------

   //Set data_Select
   assign data_select = addr;

   //------------------------------------------------------------------------
   // Set rdata demux & RLAST generatation
   //------------------------------------------------------------------------

   always @(data_select or rdata)
     begin : rdata_demux
     case (data_select)
         1'd0 : rdata_s = rdata[31:0];
         1'd1 : rdata_s = rdata[63:32];
         default : rdata_s = 32'bx;
        endcase
     end // rdata_demux

   assign rlast_s_i = last_addr_match  && rlast_in;
   assign rlast_s   = rlast_s_i;
   //------------------------------------------------------------------------
   // Valid/Ready Generation for all signals
   //------------------------------------------------------------------------

   //Archannel_ready is true when there is an empty slice (or about to be)
   assign archannel_ready_i = ~&valid_bus;
   assign archannel_ready   = archannel_ready_i;
   //Detect AR channel handshake
   assign archannel_hndshk = archannel_ready_i && archannel_valid;

   //A slice is pushed when an AR channel handhake.
   //It is identifed by push and store signals
   assign push_slice = archannel_hndshk;

   //store decode Logic
   always @(valid_bus or match_bus)
     begin : store_decode
        if (!valid_bus)
           store = 1'b1;
        else
           store = match_bus;
      end // store_decode

   //Distribute the number of the Slice reporting a Hazard
   always @(hazard_bus)
     begin : hazard_num_distibution
       case (hazard_bus)
          1'b0 : hazard_pointer = 1'b0;
           1'd1 : hazard_pointer = 1'd0;
         default : hazard_pointer = 1'bx;
       endcase
     end

   //Distribute the number of the Slice reporting a Hazard
   always @(match_bus)
     begin : match_num_distibution
       case (match_bus)
          1'b0 : match_pointer = 1'b0;
           1'd1 : match_pointer = 1'd0;
         default : match_pointer = 1'bx;
       endcase
     end

   //Detect a complete beat
   assign beat_complete = (rlast_s_i | beat_complete_slice) && update;


   //rchannel_ready
   assign rready_m = beat_complete && rvalid_m;


   //RVALIDS is alwyas true wheile there is valid data in the device
   assign rvalid_s = rvalid_m;


   //Detect handshake on the Slave R Channel
   assign rchannel_hndshk = rvalid_m && rready_s;

   //The addr registers are updated on every handshake on the Rchannel
   assign update = rchannel_hndshk;

   //The Selcted cam Slice is pop when an Slce R Channel handsake with RLAST occurs
   assign pop_slice = update && rlast_s_i;

   //------------------------------------------------------------------------
   // CAM SLices
   //------------------------------------------------------------------------

    
     //Cam Slice number 0 //
     nic400_ib_psram_slv_axi4_ib_upsize_rd_cam_slice_ysyx_rv32 u_upsize_rd_cam_slice_0
     (
         // global signals
        .aresetn              (aresetn),
        .aclk                 (aclk),

        // ID inputs (to all slices)
        .match_id              (rid_m),

        //Control Signals
        .store                (store),
        .push_slice           (push_slice),
        .pop_slice            (pop_slice),
        .update               (update),
        .match_pointer        (match_pointer),

        .archannel_data       (archannel_data),
        .rlast_in             (rlast_in),
        
        .hazard_in            (hazard),
        .hazard_pointer       (hazard_pointer),

        //Outputs
        .hazard               (hazard_bus),
        .match                (match_bus),
        .valid                (valid_bus),
        .addr_out             (addr_out0),
        .last_addr_match      (last_addr_match_bus),
        .beat_complete        (beat_complete_slice_bus)
     );
     


`ifdef ARM_ASSERT_ON

   //------------------------------------------------------------------------
   // OVL_ASSERT: Check that only one Slice ever matches
   //------------------------------------------------------------------------
   // If more than one slot matches the hazard detection logic has gone wrong
   //------------------------------------------------------------------------

   // OVL_ASSERT_RTL
  assert_never_unknown #(0,1,"Rd Channel Slice match has gone wrong")  
  ovl_single_ID_match
    (
     .clk              (aclk),
     .reset_n          (aresetn),
     .qualifier        (match_bus),
     .test_expr        (rchannel_hndshk)
     );
   // OVL_ASSERT_END

   //------------------------------------------------------------------------
   // OVL_ASSERT: Check that only one Slice ever reports a hazard
   //------------------------------------------------------------------------
   // If more than one slot matches the last detection logic has gone wrong
   //------------------------------------------------------------------------

   // OVL_ASSERT_RTL
  assert_never_unknown #(0,1,"Rd Channel Slice hazard has gone wrong")
  ovl_single_hazard
    (
     .clk              (aclk),
     .reset_n          (aresetn),
     .qualifier        (hazard_bus),
     .test_expr        (archannel_hndshk)
     );
   // OVL_ASSERT_END



`endif

endmodule

`include "nic400_ib_psram_slv_axi4_ib_undefs_ysyx_rv32.v"

